#include <unordered_map>
#include <string>
#include <sstream>
#include <fstream>
#include <sys/socket.h>
using namespace std;
const string blank = " ";
const string mark = "\r\n";
const string kv_mark = ": ";
const string webroot = "./wwwroot";
const string homepage = "index.html";
const string errofile = "404.html";
typedef struct httpRequest
{
    string _method;
    string _uri;
    string _versions;
    unordered_map<string, string> _head_data;
    string _text;
} httpRequest;
typedef struct httpResponse
{
    string _versions;
    int _state_code;
    string _state;
    unordered_map<string, string> _head_data;
    string _text;
} httpResponse;
class Http
{
public:
    Http()
    {
    }
    // 解包（反序列化）
    inline bool GetOneline(string &out, string &src)
    {
        int pos = src.find(mark);
        if (pos == string::npos)
            return false;
        out = src.substr(0, pos);
        src = src.erase(0, pos + mark.size());
        return true;
    }
    bool Deserilize(string src) // 只有一个完整的http报头
    {
        // 提取请求行
        string out;
        GetOneline(out, src);
        // 解包请求行
        stringstream ss(out);
        ss >> _req._method >> _req._uri >> _req._versions;
        // 提取并解包请求报头
        out.clear();
        while (out != "")
        {
            int pos = out.find(kv_mark);
            if (pos == string::npos)
                return false;
            _req._head_data[out.substr(0, pos)] = out.substr(pos + kv_mark.size());
            out.clear();
            GetOneline(out, src);
        }
        // 提取请求正文
        _req._text = src;
        return true;
    }
    // 封包（序列化）
    // void Serilize(string &out)
    string Serilize()
    {
        // 响应行
        string out;
        out += _rsp._versions + blank + to_string(_rsp._state_code) + blank + _rsp._state;
        out += mark;
        // 响应报头
        for (auto [key, val] : _rsp._head_data)
        {
            out += key + kv_mark + val + mark;
        }
        out += mark; // 空行
        // 响应正文
        out += _rsp._text;
        return out;
    }
    void setVersion(string vs)
    {
        _rsp._versions = vs;
    }
    void setCode(int code)
    {
        _rsp._state_code = code;
        switch (code)
        {
        case 200:
            _rsp._state = "Success";
            break;
        case 404:
            _rsp._state = "Not Found";
            break;
        // 永久重定向
        case 301:
            _rsp._state = "Moved Permanently";
        // 临时重定向
        case 302:
            _rsp._state = "See Other";
        //......
        default:
            _rsp._state = "None";
            break;
        }
    }
    void setHeader(string key, string val)
    {
        _rsp._head_data.insert({key, val});
    }
    void setText()
    {
        string file;
        if (_req._uri == "/")
            file = webroot + _req._uri + homepage;
        else
            file = webroot + _req._uri;

        // 检查uri文件是否存在
        ifstream in(file);
        if (!in.is_open())
        {
            file = webroot + '/' + errofile;
            _req._uri = errofile;
        }
        // 将文件内容写入响应正文
        in.seekg(0, in.end);
        int size = in.tellg();
        in.seekg(0, in.beg);
        _rsp._text.resize(size);
        in.read((char *)(_rsp._text.c_str()), size);
        in.close();
    }
    string getReqHeader(string key)
    {
        auto out = _req._head_data.find(key);
        if (out == _req._head_data.end())
            return "";
        return out->second;
    }
    string getHttpMethod() { return _req._method; }
    string getUri() { return _req._versions; }
    string getText() { return _req._text; }
    ~Http()
    {
    }
    // 请求报头
    httpRequest _req;
    // 响应报头
    httpResponse _rsp;
};